Repository navigation
fix(shader): sample a 3D T# through DIM 2D_ARRAY as a volume - #7381
Conversation
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Second-GPU run on head
Not checked: PPSA31327, the full Written with Claude Code assistance (validation by a subagent, reviewed in this session). |
f405b7c to
15882ea
Compare
|
Tested at
Small wording point: the debt entry says the Z mode "wraps or clamps", but the measurement used wrap only. AI-assisted: yes (Claude Code); results above were run on this machine. |
|
Tested on Windows 11, MinGW-w64 GCC 15.2.0, NVIDIA GeForce RTX 5090 (driver 617.42), Ryzen 9 9950X3D. Head Cause: this PR adds With only that assertion changed to AI-assisted: yes. Written with AI assistance and reviewed by me. |
|
PPSA31327 (Yakuza 0 Director's Cut 01.015.000) with this branch, as asked. Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release, RTX 4070 (617.42).
To build on that AI-assisted: yes |
15882ea to
1b32568
Compare
|
Thanks @klosixgaming-arch and @johandavidcm for catching the silent count merge, and @johandavidcm for the Yakuza 0 run. Rebased onto
On the RX 6700 XT the volume test, The body now lists your runs. |
|
Rebase handoff — rebased onto current Verified on Linux (CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, To pick it up: Head is |
|
Correction: the pushed |
|
The clean branch is re-pushed: head |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1b32568 to
1ed8eb6
Compare
|
Checked the tracker and materializer changes (loads, gathers, bias, comparison and mixed load+sample all clear the flag; a real 2D-array T# still picks the 2D-array mode), the execution test (it fails on |
Rewrite the debt entry added by #7381 so it opens with what is unverified (RDNA2 gfx1031 only, wrap addressing only), keeps the Z_FILTER difference, and lists everything that still throws: the other sample forms, gathers, image_get_lod and image_get_resinfo, and the three samples of a T# selected from an image table, of a T# also loaded with DIM 2D_ARRAY, and of an 11_11_10_UNORM, 11_11_10_UINT or depth-bits T#. The entry goes from 1286 to 898 characters. Co-Authored-By: Claude <noreply@anthropic.com>
What
Yakuza 0 Director's Cut (PPSA31327) stops a few seconds into its first cutscene (discussion #6722):
The pixel shader samples a 3D RGBA8 T# with DIM 2D_ARRAY image instructions. #5555 accepts 2D-array loads and stores on a 3D T#, and #5461 accepts biased DIM 2D samples of a one-slice volume, but a 2D-array sample of a volume has no runtime mode.
I measured what RDNA2 does with the hardware oracle template, run through the Windows driver's comgr and HIP runtime on an RX 6700 XT (gfx1031). On 16x16x4 R32_FLOAT 3D T#s with one and three levels,
image_sample,image_sample_landimage_sample_lzwith DIM 2D_ARRAY returned the same value as the same instruction with DIM 3D in all 256 lanes of 66 cases:image_sample_l.So the third address VGPR is the normalized r coordinate, addressed by the sampler's Z mode, not a layer index. These cases used wrap only: r = 1.0 reads slice 0 and r = 0.375 slice 1.
This change adds a Dim3D runtime mode for a 2D-array sampled image whose accesses are all
image_sample,image_sample_lorimage_sample_lz(new tracker flagvolumeArraySampleCompatible, the same instruction set ascubeFaceCompatible). The emitter already samples a Dim3D mode with the instruction's three coordinates, and the driver already binds a 3D T# as a 3D view withaddressModeWfrom CLAMP_Z, so neither needed a change.These keep throwing, because they are not measured:
image_get_lod;ImageResourcehas a new field, so the shader disk cache format goes from 40 to 41 and theImageResourcefield count from 39 to 40. (maintook 38, 39 and 40 for other format changes, and field count 39 for #5958's field, after this PR was opened.)Overlap:
ImageResourcefield and edit the samefieldCount<ImageResource>()line. As @klosixgaming-arch found, two PRs that make the same count edit merge without a conflict, and the result fails to build. Whichever lands second has to raise the count again.cubeFaceCompatibleline that the new flag's line follows, and the debt entry after the new one.FormatVersiontoo.Tested
Windows 11 26200, AMD Radeon RX 6700 XT (gfx1031), driver 32.0.21045.5002, WinLibs GCC 15.2.0 r7, Release,
BUILD_TESTING=ON,ANYPS5_REQUIRE_VULKAN=1:agc_driver_image_array_sample_on_volume: a compute shader on a 16x16x4 RGBA8 3D T# with a repeat point sampler.image_sample_lzwith DIM 3D and with DIM 2D_ARRAY, andimage_sample_lwith DIM 2D_ARRAY, are given r = (z + 0.5) / 4 + k for k from -1 to 2, and must return slice z.image_sample_lwith LOD 1 must return slice z / 2 of level 1, with DIM 3D and with DIM 2D_ARRAY. Each level has its own markers, so reading the LOD from the wrong register would fail.image_sample_bwith DIM 2D_ARRAY must still be refused.main2626e5ee7it fails with the title's message:image descriptor is incompatible with the static runtime image interface: descriptor format 56 decodes to {class 1, dim 4, conversion 0, packed 0, cube 0, depthBits 0, unorm16 0, srgb 0}.agc_shader_memory(verifyVolumeArrayLoadMode): the flag selects the Dim3D mode for a 3D T#, a 2D-array T# still selects the 2D-array mode, and without the flag a sample on a 3D T# is still refused.agc_shader_disk_cache: the new field round-trips.main7f596df48on 2026-10-19, head 1b32568.mainhad takenFormatVersion40 andfieldCount<ImageResource>()39 (feat(shader): sample converted unorm images in the shader #5958) for other fields, so this now raises them to 41 and 40. Before this rebase the count edit merged silently withmain's identical one and the merge failed to build, as @klosixgaming-arch and @johandavidcm found.agc_driver_image_array_sample_on_volume,agc_shader_memoryandagc_shader_disk_cachepass 2 of 2 on 1b32568 on the RX 6700 XT.ctest --parallel 4 --timeout 120onmain7f596df48with this change: 1604 tests, 17 fail, none from this PR:conventions_*andhardware_oracle_compare(CI'sconventionsjob passes on this head);guest_pthread_rwlockandguest_file_lock_process, under load;main's three known AMD failures:agc_driver_lds_mixed_width_atomics(fix(shader): release the LDS lock with an exchange and drop fences inside it #6976),agc_driver_lds_lock_budget(AGC: AMD device-backed LDS lock-budget case returns half of expected sum #7344),agc_driver_layered_volume_vertex_no_gpl(AMD Windows: GPL-mode cache failures (alpha/wave32 pass after local driver update) #4768);agc_driver_layered_volume_draw,agc_driver_layered_volume_vertex,agc_driver_draw_cache_reuse_offandagc_driver_stencil_replay_no_gpl(VK_ERROR_DEVICE_LOSTat the first submit). All four pass from renamed copies of their executables, so they hit stale entries in AMD's per-executable pipeline cache;agc_driver_store_idle_resultsfailed once and passed when rerun.1002:13c0, 32.0.21042.62). WithResourceMaterializer.cppandResourceTracker.cppset back tomain,agc_shader_memoryand the volume test fail on both. Nothing else in the 716-testagc_|shader|recompilerset changes status.ctest --parallel 4 --timeout 120onmain1e2d9b369with this change: 1463 tests. The only failures are three AMD GPU tests that fail without it on this machine too:agc_driver_lds_mixed_width_atomics(fix(shader): release the LDS lock with an exchange and drop fences inside it #6976),agc_driver_lds_lock_budget(AGC: AMD device-backed LDS lock-budget case returns half of expected sum #7344) andagc_driver_layered_volume_vertex_no_gpl(AMD Windows: GPL-mode cache failures (alpha/wave32 pass after local driver update) #4768).python tools/check_conventions.py --base origin/mainwith this title and body passes.Hardware measurement (RX 6700 XT, gfx1031, driver 32.0.21045.5002): DIM 2D_ARRAY vs DIM 3D, lane by lane
Each case runs the same instruction twice in separate processes, once with DIM 2D_ARRAY and once with DIM 3D, over 256 lanes in 2x2 quads, and compares all four returned components of every lane. The T# is a 16x16x4 R32_FLOAT volume (
SW_MODE9) over memory where every dword holds its own index, so a value names the dword (or blend) the hardware read. The sampler wraps in x, y and z, withMAX_LOD0xfff.image_sample_lzimage_sample_lzZ_FILTER0image_sample_lzimage_sampleimage_sample_lzimage_sample_l(LOD 1)With point filtering and one level, r = 0, 0.125 read slice 0, 0.375 slice 1, 0.5 and 0.625 slice 2, 0.875 slice 3, 1.0, 1.125, 2.0 and 3.0 slice 0, 1.5 slice 2 and -0.125 slice 3, for both DIM values.
image_loadwith DIM 2D_ARRAY takes the integer slice instead, as #5555 implements. With point filtering and three levels, lane 0 of a plainimage_samplewhose r steps by 2 slices across its quad reads dword 19456, as when u and v step by 2 texels, instead of the 23552 that a 1-texel step with constant r reads, with either DIM value. So r's derivative takes part in the LOD.Kernel core (the T# is built in s[24:31] from the input buffer address, the sampler in s[32:35]):
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)1002:13c0(@wachi35676), RTX 5090 (@klosixgaming-arch)🤖 Generated with Claude Code